home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Ports / msdos / dir.c next >
Encoding:
C/C++ Source or Header  |  1991-04-23  |  3.2 KB  |  183 lines  |  [TEXT/????]

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1990. */
  2.  
  3. /*
  4.  * MS-DOS version of UNIX directory access package.
  5.  * (opendir, readdir, closedir).
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11. #include <dos.h>
  12. #include <errno.h>
  13. #include <sys\types.h>
  14. #include <sys\stat.h>
  15. #include "dir.h"
  16.  
  17. #define Visible
  18. #define Hidden static
  19. #define Procedure
  20.  
  21. typedef int bool;
  22.  
  23. #define Yes ((bool) 1)
  24. #define No  ((bool) 0)
  25.  
  26. #define MAXPATH 64
  27. #define EOS '\0'
  28.  
  29. extern int errno;
  30. Hidden char *firstf();
  31. Hidden char *nextf();
  32.  
  33. Hidden char dirpath[MAXPATH+1] = "";
  34. Hidden bool busy = No;
  35.  
  36. /*
  37.  * Open a directory.
  38.  * This MS-DOS version allows only one directory to be open at a time.
  39.  * The path must exist and be a directory.
  40.  * Then it only saves the file name and returns a pointer to it.
  41.  */
  42.  
  43. Visible DIR *opendir(path)
  44.      char *path;
  45. {
  46.     struct stat buffer;
  47.  
  48.     if (dirpath[0] != EOS) {
  49.          errno = EMFILE;
  50.          return NULL; /* Only one directory can be open at a time */
  51.     }
  52.     if (stat(path, &buffer) == -1)
  53.         return NULL; /* Directory doesn't exist */
  54.     if ((buffer.st_mode & S_IFMT) != S_IFDIR) {
  55.         errno = ENOENT;
  56.         return NULL; /* Not a directory */
  57.     }
  58.     strcpy(dirpath, path);
  59.     path = dirpath + strlen(dirpath);
  60.     if (path > dirpath && path[-1] != ':' && path[-1] != '/' &&
  61.             path[-1] != '\\')
  62.         *path++ = '\\';
  63.     strcpy(path, "*.*");
  64.     busy = No; /* Tell readdir this is the first time */
  65.     return (DIR *) dirpath;
  66. }
  67.  
  68. /*
  69.  * Read the next directory entry.
  70.  */
  71.  
  72. Visible struct direct *readdir(dp)
  73.      char *dp;
  74. {
  75.     static struct direct buffer;
  76.     char *p;
  77.  
  78.     if (!busy)
  79.         p = firstf((char *)dp);
  80.     else
  81.         p = nextf();
  82.     busy = (p != NULL);
  83.     if (!busy)
  84.         return NULL;
  85.     strcpy(buffer.d_name, p);
  86.     buffer.d_namlen = strlen(p);
  87.     return &buffer;
  88. }
  89.  
  90.  
  91. /*
  92.  * Close a directory.
  93.  * We must clear the first char of dirpath to signal opendir that
  94.  * no directory is open.
  95.  */
  96.  
  97. Visible Procedure closedir(dirp)
  98.      DIR *dirp;
  99. {
  100.     dirp[0] = EOS;
  101. }
  102.  
  103. /*
  104.  * Low-level implementation -- access to DOS system calls FIRST and NEXT.
  105.  */
  106.  
  107. Hidden char dta[64]; /* Device Transfer Area */
  108.  
  109. #define DIRATTR 0x10
  110.  
  111. Hidden char *firstf(pat)
  112.      char *pat;
  113. {
  114.     static int flags;
  115.     union REGS regs;
  116.     struct SREGS segregs;
  117.  
  118.     setdta(dta);
  119.  
  120.     segread(&segregs);
  121.     regs.h.ah = 0x4e;
  122.     regs.x.cx = DIRATTR;
  123. #ifdef M_I86LM /* Large Model -- far pointers */
  124.     regs.x.dx = FP_OFF(pat);
  125.     segregs.ds = FP_SEG(pat);
  126. #else
  127.     regs.x.dx = (int) pat;
  128. #endif
  129.     flags = intdosx(®s, ®s, &segregs);
  130.     if (regs.x.cflag)
  131.       return NULL;
  132.     fixfile();
  133.     return dta + 30;
  134. }
  135.  
  136. Hidden char *nextf()
  137. {
  138.     int flags;
  139.     union REGS regs;
  140.  
  141.     setdta(dta);
  142.  
  143.     regs.h.ah = 0x4f;
  144.     flags = intdos(®s, ®s);
  145.     if (regs.x.cflag)
  146.       return NULL;
  147.     fixfile();
  148.     return dta + 30;
  149. }
  150.  
  151. /*
  152.  * Convert the file name in the Device Transfer Area to lower case.
  153.  */
  154.  
  155. Hidden Procedure fixfile()
  156. {
  157.     char *cp;
  158.  
  159.     for (cp = dta+30; *cp != EOS; ++cp)
  160.       *cp = tolower(*cp);
  161. }
  162.  
  163. /*
  164.  * Tell MS-DOS where the Device Transfer Area is.
  165.  */
  166.  
  167. Hidden Procedure setdta(dta)
  168.      char *dta;
  169. {
  170.     union REGS regs;
  171.     struct SREGS segregs;
  172.  
  173.     segread(&segregs);
  174.     regs.h.ah = 0x1a;
  175. #ifdef M_I86LM /* Large Model -- far pointers */
  176.     regs.x.dx = FP_OFF(dta);
  177.     segregs.ds = FP_SEG(dta);
  178. #else
  179.     regs.x.dx = (int) dta;
  180. #endif
  181.     intdosx(®s, ®s, &segregs);
  182. }
  183.